package xyz.mumuwei.youthcourseserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import xyz.mumuwei.youthcourseserver.common.dto.PageDto;
import xyz.mumuwei.youthcourseserver.common.lang.Result;
import xyz.mumuwei.youthcourseserver.job.SendWechatReserveMessageJob;
import xyz.mumuwei.youthcourseserver.mapper.OrderMapper;
import xyz.mumuwei.youthcourseserver.mapper.StudentCourseMapper;
import xyz.mumuwei.youthcourseserver.mapper.UserInfoMapper;
import xyz.mumuwei.youthcourseserver.mapper.UserMapper;
import xyz.mumuwei.youthcourseserver.pojo.*;
import xyz.mumuwei.youthcourseserver.service.StudentCourseService;
import xyz.mumuwei.youthcourseserver.utils.QuartzUtil;
import xyz.mumuwei.youthcourseserver.utils.TimeUtil;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author mumuwei
 * @since 2022-02-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StudentCourseServiceImpl extends ServiceImpl<StudentCourseMapper, StudentCourse> implements StudentCourseService {

    final UserMapper userMapper;
    final UserInfoMapper infoMapper;
    final OrderMapper orderMapper;
    final StudentCourseMapper studentCourseMapper;

    /**
     * 根据用户id和课程获取课时列表，包含用户预约状态
     *
     * @param uid      用户账户id
     * @param courseId 课程id
     * @return 课时列表，包含预约情况
     */
    @Override
    public Result getClassTimeListByCourseId(Integer uid, Integer courseId) {
        // 判断用户是否该买该课程
        Integer studentId = getStudentId(uid);
        if (studentId == null) {
            return Result.fail("用户信息不存在！");
        }
        Order order = orderMapper.selectOne(
                new QueryWrapper<Order>()
                        .eq("course_id", courseId)
                        .eq("student_id", studentId)
                        .eq("state", 0));
        if (order == null) {
            return Result.fail("您未购买该课程！");
        }

        // 学生已购买课程
        List<CourseTime> timeList = studentCourseMapper.getCourseClassTimeListByCourseId(uid, courseId);
        return Result.success(timeList);
    }

    /**
     * 根据用户账户id和课时id预约课程
     *
     * @param uid         用户账户id
     * @param classTimeId 课时id
     * @return 预约结果
     */
    @Override
    public Result reserveClassTime(Integer uid, Integer classTimeId) throws SchedulerException {
        Integer studentId = getStudentId(uid);
        if (studentId == null) {
            return Result.fail("学生信息不存在！");
        }
        // 学生id存在，检查学生是否购买该课程
        CourseTime courseTime = studentCourseMapper.checkStudentBuyCourseByClassTime(studentId, classTimeId);
        if (courseTime == null) {
            return Result.fail("预约错误，为购买该课程！");
        }

        // 学生已购买该课程
        StudentCourse studentCourse = new StudentCourse();
        studentCourse.setStudentId(studentId);
        studentCourse.setCourseTimeId(classTimeId);
        int insert = studentCourseMapper.insert(studentCourse);
        if (insert <= 0) {
            return Result.fail("预约失败！");
        }

        // 预约后定时发送微信订阅消息
        User user = userMapper.selectById(uid);
        if(user.getOpenId() != null) {
            // 设置数据
            HashMap<String, Object> map = new HashMap<>(3);
            map.put("courseId", courseTime.getCourseId());
            map.put("openId", user.getOpenId());
            map.put("timeId", classTimeId);

            String startTime = courseTime.getStartTime();
            String jobName = uid + "" + courseTime.getCourseId() + startTime;

            String time19 =
                    String.valueOf(
                            Integer.parseInt(
                                    TimeUtil.getStartOfDay(
                                            new Date(Long.parseLong(startTime + "000")))) - 5*60*60);
            String time2 = String.valueOf(Long.parseLong(startTime)-2*60*60);

            // 课程前日19点提醒一次
            QuartzUtil.getInstance().addJob(SendWechatReserveMessageJob.class,
                    jobName + "19",
                    "classTimeMessage",
                    TimeUtil.dateFormat(time19,"0 0 kk dd MM ? yyyy"),
                    map);

            // 课程当日提前2小时提醒
            QuartzUtil.getInstance().addJob(SendWechatReserveMessageJob.class,
                    jobName + "2",
                    "classTimeMessage",
                    TimeUtil.dateFormat(time2, "0 0 kk dd MM ? yyyy"),
                    map);
            log.info("预约课程课时成功，开启预约课时课前提醒！jobName:{}", jobName);
        }
        return Result.success("预约成功！");
    }

    /**
     * 根据用户账户id和课时id 取消预约课程
     *
     * @param uid         用户账户id
     * @param classTimeId 课时id
     * @return 取消预约结果
     */
    @Override
    public Result unReserveClassTime(Integer uid, Integer classTimeId) throws SchedulerException {
        Integer studentId = getStudentId(uid);
        if (studentId == null) {
            return Result.fail("学生信息不存在");
        }

        // 获取学生预约课程记录
        StudentCourse studentCourse = studentCourseMapper.selectOne(
                new QueryWrapper<StudentCourse>()
                        .eq("student_id", studentId)
                        .eq("course_time_id", classTimeId));

        // 若预约记录不为空，删除记录
        if (studentCourse != null) {
            studentCourseMapper.deleteById(studentCourse.getId());

            // 清除定时消息
            CourseTime courseTime = studentCourseMapper.checkStudentBuyCourseByClassTime(studentId, classTimeId);
            String startTime = courseTime.getStartTime();
            String jobName = uid + "" + courseTime.getCourseId() + startTime;

            QuartzUtil.getInstance().deleteJob(jobName + "2", "classTimeMessage");
            QuartzUtil.getInstance().deleteJob(jobName + "19", "classTimeMessage");
            log.info("取消预约课程课时成功，删除预约课时课前提醒！jobName：{}", jobName );
        }
        return Result.success("取消预约成功！");
    }

    /**
     * 根据课程id和课时id获取预约课程课时学生列表(不分页)
     *
     * @param courseId    课程id
     * @param classTimeId 课时id
     * @return 预约列表
     */
    @Override
    public Result getReserveListByCourseId(Integer courseId, Integer classTimeId) {
        List<StudentCourse> list = studentCourseMapper.getReserveListByCourseId(courseId, classTimeId);
        return Result.success(list);
    }

    /**
     * 根据课程id和课时id获取预约课程课时学生列表(分页)
     *
     * @param courseId 课程id
     * @param pageDto  分页信息和课时id
     * @return 预约列表
     */
    @Override
    public Result getReservePageByCourseId(Integer courseId, PageDto pageDto) {
        pageDto.setStart((pageDto.getCurrent()-1)*pageDto.getSize());
        pageDto.setEnd(pageDto.getCurrent()*pageDto.getSize());
        pageDto.setId(courseId);
        List<StudentCourse> page = studentCourseMapper.getReservePageByCourseId(pageDto);

        Page<StudentCourse> classTimePage = new Page<>(pageDto.getCurrent(), pageDto.getSize());
        classTimePage.setRecords(page);
        if (page.size() <= 0) {
            classTimePage.setTotal(0);
            return Result.success(classTimePage);
        }
        classTimePage.setTotal(
                studentCourseMapper
                        .selectCount(new QueryWrapper<StudentCourse>()
                                .eq("course_time_id", pageDto.getClassTimeId())
                        ));
        return Result.success(classTimePage);
    }

    /**
     * 根据用户据账户id获取学生id
     */
    private Integer getStudentId(Integer uid) {
        UserInfo userInfo = infoMapper.selectOne(new QueryWrapper<UserInfo>().eq("user_id", uid));
        if (userInfo != null) {
            return userInfo.getId();
        }
        return 0;
    }
}
